<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <title>Configuring locking: sizing the system</title>
    <link rel="stylesheet" href="gettingStarted.css" type="text/css" />
    <meta name="generator" content="DocBook XSL Stylesheets V1.73.2" />
    <link rel="start" href="index.html" title="Berkeley DB Programmer's Reference Guide" />
    <link rel="up" href="lock.html" title="Chapter 18.  The Locking Subsystem" />
    <link rel="prev" href="lock_config.html" title="Configuring locking" />
    <link rel="next" href="lock_stdmode.html" title="Standard lock modes" />
  </head>
  <body>
    <div xmlns="" class="navheader">
      <div class="libver">
        <p>Library Version 12.1.6.2</p>
      </div>
      <table width="100%" summary="Navigation header">
        <tr>
          <th colspan="3" align="center">Configuring locking: sizing the
        system</th>
        </tr>
        <tr>
          <td width="20%" align="left"><a accesskey="p" href="lock_config.html">Prev</a> </td>
          <th width="60%" align="center">Chapter 18.  The Locking Subsystem </th>
          <td width="20%" align="right"> <a accesskey="n" href="lock_stdmode.html">Next</a></td>
        </tr>
      </table>
      <hr />
    </div>
    <div class="sect1" lang="en" xml:lang="en">
      <div class="titlepage">
        <div>
          <div>
            <h2 class="title" style="clear: both"><a id="lock_max"></a>Configuring locking: sizing the
        system</h2>
          </div>
        </div>
      </div>
      <p>
        The amount of memory available to the locking system is
        specified using the <a href="../api_reference/C/envset_memory_max.html" class="olink">DB_ENV-&gt;set_memory_max()</a> method. Sizing of the
        enviroment using the <a href="../api_reference/C/envset_memory_max.html" class="olink">DB_ENV-&gt;set_memory_max()</a> method is discussed
        in <a class="xref" href="env_size.html" title="Sizing a database environment">Sizing a database environment</a>. Here
        we will discuss how to estimate the number of objects your
        application is likely to lock. Since running out of memory for
        locking structures is a fatal error requiring reconfiguration
        and restarting the environment it is best to overestimate the
        numbers.
    </p>
      <p> 
        When configuring a Berkeley DB Concurrent Data Store
        application, the number of lock objects needed is two per open
        database (one for the database lock, and one for the cursor
        lock when the <a href="../api_reference/C/envset_flags.html#set_flags_DB_CDB_ALLDB" class="olink">DB_CDB_ALLDB</a> option is not specified). The
        number of locks needed is one per open database handle plus
        one per simultaneous cursor or non-cursor operation.
    </p>
      <p> 
        Configuring a Berkeley DB Transactional Data Store
        application is more complicated. The recommended algorithm for
        selecting the number of locks, lockers, and lock objects is to
        run the application under stressful conditions and then review
        the lock system's statistics to determine the number of locks,
        lockers, and lock objects that were used. Then, double these
        values for safety. However, in some large applications, finer
        granularity of control is necessary in order to minimize the
        size of the Lock subsystem. 
    </p>
      <p> 
        The number of lockers can be estimated as follows: 
    </p>
      <div class="itemizedlist">
        <ul type="disc">
          <li> 
            If the database environment is using transactions,
            the number of lockers can be estimated by adding the
            number of simultaneously active non-transactional cursors
            and open database handles to the number of simultaneously
            active transactions and child transactions (where a child
            transaction is active until it commits or aborts, not
            until its parent commits or aborts).
        </li>
          <li> 
            If the database environment is not using
            transactions, the number of lockers can be estimated by
            adding the number of simultaneously active
            non-transactional cursors and open database handles to the
            number of simultaneous non-cursor operations. 
        </li>
        </ul>
      </div>
      <p> 
        The number of lock objects needed for a transaction can be
        estimated as follows: 
    </p>
      <div class="itemizedlist">
        <ul type="disc">
          <li>
            <p> 
                For each access to a non-Queue database, one lock
                object is needed for each page that is read or
                updated.
            </p>
          </li>
          <li>
            <p>
                For the Queue access method you will need one lock
                object per record that is read or updated. Deleted
                records skipped by a DB_NEXT or DB_PREV operation do
                not require a separate lock object.
            </p>
          </li>
          <li>
            <p>
                For Btree and Recno databases additional lock
                objects may be needed for each node in the btree that
                has to be split due to an update. 
            </p>
          </li>
          <li>
            <p>
                For Hash and Queue databases, every access must
                obtain a lock on the metadata page for the duration of
                the access. This is not held to the end of the
                transaction.
            </p>
          </li>
          <li>
            <p> 
                If the transaction performs an update that needs to
                allocate a page to the database then a lock object for
                the metadata page will be needed to the end of the
                transaction. 
            </p>
          </li>
        </ul>
      </div>
      <p>
        Note that transactions accumulate locks over the
        transaction lifetime, and the lock objects required by a
        single transaction is the total lock objects required by all
        of the database operations in the transaction. However, a
        database page (or record, in the case of the Queue access
        method), that is accessed multiple times within a transaction
        only requires a single lock object for the entire transaction.
        So if a transaction in your application typically accesses 10
        records, that transaction will require about 10 lock objects
        (it may be a few more if it splits btree nodes). If you have
        up to 10 concurrent threads in your application, then you need
        to configure your system to have about 100 lock objects. It is
        always better to configure more than you need so that you
        don't run out of lock objects. The memory overhead of
        over-allocating lock objects is minimal as they are small
        structures. 
    </p>
      <p>
        The number of locks required by an application cannot be
        easily estimated. It is possible to calculate a number of
        locks by multiplying the number of lockers, times the number
        of lock objects, times two (two for the two possible lock
        modes for each object, read and write). However, this is a
        pessimal value, and real applications are unlikely to actually
        need that many locks. Reviewing the Lock subsystem statistics
        is the best way to determine this value.
    </p>
      <p>
        By default a minimum number of locking objects are
        allocated at startup. To avoid contention due to allocation
        the application may use the <a href="../api_reference/C/envset_memory_init.html" class="olink">DB_ENV-&gt;set_memory_init()</a> method to
        preallocate and initialize the following lock structures:
    </p>
      <div class="itemizedlist">
        <ul type="disc">
          <li>
            <p>
                <code class="literal">DB_MEM_LOCK</code>
            </p>
            <p> 
                Specifies the number of locks that can be
                simultaneously requested in the system. 
            </p>
          </li>
          <li>
            <p>
                <code class="literal">DB_MEM_LOCKER</code>
            </p>
            <p> 
                Specifies the number of lockers that can
                simultaneously request locks in the system. 
            </p>
          </li>
          <li>
            <p>
                <code class="literal">DB_MEM_LOCKOBJECTS</code>
            </p>
            <p> 
                Specifies the number of objects that can
                simultaneously be locked in the system. 
            </p>
          </li>
        </ul>
      </div>
      <p>
        In addition to the above structures, sizing your locking
        subsystem also requires specifying the number of lock table
        partitions. You do this using the <a href="../api_reference/C/envset_lk_partitions.html" class="olink">DB_ENV-&gt;set_lk_partitions()</a>
        method. Each partition may be accessed independently by a
        thread. More partitions can lead to higher levels of
        concurrency. The default is to set the number of partitions to
        be 10 times the number of cpus that the operating system
        reports at the time the environment is created. Having more
        than one partition when there is only one cpu is not
        beneficial because the locking system is more efficient when
        there is a single partition. Some operating systems (Linux,
        Solaris) may report thread contexts as cpus, and so it may be
        necessary to override the default to force a single partition
        on a single hyperthreaded cpu system. Objects and locks are
        divided among the partitions so it is best to allocate several
        locks and objects per partition. The system will force there
        to be at least one per partition. If a partition runs out of
        locks or objects it will steal what is needed from the other
        partitions. This operation could impact performance if it
        occurs too often. The final values specified for the locks and
        lock objects should be more than or equal to the number of
        lock table partitions.
    </p>
    </div>
    <div class="navfooter">
      <hr />
      <table width="100%" summary="Navigation footer">
        <tr>
          <td width="40%" align="left"><a accesskey="p" href="lock_config.html">Prev</a> </td>
          <td width="20%" align="center">
            <a accesskey="u" href="lock.html">Up</a>
          </td>
          <td width="40%" align="right"> <a accesskey="n" href="lock_stdmode.html">Next</a></td>
        </tr>
        <tr>
          <td width="40%" align="left" valign="top">Configuring locking </td>
          <td width="20%" align="center">
            <a accesskey="h" href="index.html">Home</a>
          </td>
          <td width="40%" align="right" valign="top"> Standard lock modes</td>
        </tr>
      </table>
    </div>
  </body>
</html>
